﻿#include "handle.h"

Handle::Handle(int num)
{
    this->id=QHostInfo::localHostName();
    this->num=num;
    QStringList computer_data=get_computerinfo();

    bool ok;
    int threadCount=computer_data[1].toInt(&ok,10);
    if(ok)
    {
        if(threadCount>1)
        {
            this->caculate_count=threadCount-1;
        }
        else
        {
            this->caculate_count=1;
        }
    }
    else
    {
        qDebug()<<"计算机自身参数获取错误！";
        return;
    }
}



void Handle::handle_localSocket(QString id, QString type, QString data,local_socket *l_socket,Handle *handle,emit_type te_ype)
{
    if (te_ype==One&&handle!=this)
    {
        return;
    }
    if(type=="获取服务类型")
    {
        QString senddata;
        Common::ConfigureLock.lockForRead();
        if(Common::Caculate_Count==-1)
        {
            senddata="计算节点&"+QString::number(caculate_count);
        }
        else
        {
            qDebug()<<"pp"<<Common::Caculate_Count;
            senddata="计算节点&"+QString::number(Common::Caculate_Count);
        }
        Common::ConfigureLock.unlock();
        emit this->l_SocketSendData(id,type,senddata,l_socket,One,"");
    }
    else if(type=="计算模块状态")
    {
        LocalSockt_unfinshsenddata(l_socket);
        M_Socket *tcpsocket=Common::GetTcp_Socket();
        if(tcpsocket==NULL)
        {
            qDebug()<<"当前无法连接负载均衡服务器!";
            return ;
        }
        QString computerdata=get_computerinfo().join("&&&");
        QString senddata=computerdata+"***"+data;
        emit this->t_SocketSendData(this->id,"计算模块状态",senddata,tcpsocket->t_socket,One,"");

    }
    else if(type=="handle")
    {
        QStringList Task_data=data.split("@@@");
        if(Task_data.size()<2)
        {
            qDebug()<<"解析handle任务失败";
            return ;
        }
        QString Task_id=Task_data[0];
        Common::Localsocket_CaculatedataLock.lockForWrite();
        Common::Localsocket_Caculatedata.remove(Task_id);
        Common::Localsocket_CaculatedataLock.unlock();
        M_Socket *tcpsocket=Common::GetTcp_Socket();
        if(tcpsocket==NULL)
        {
            qDebug()<<"当前无法连接负载均衡服务器!";
            return ;
        }
        emit this->t_SocketSendData(this->id,"计算结果",data,tcpsocket->t_socket,One,"");
    }
    else if(type=="DLL调用失败" || type=="任务文件解析失败" || type=="unknow")
    {
        if(!data.isEmpty())
        {
            Common::Localsocket_CaculatedataLock.lockForWrite();
            Common::Localsocket_Caculatedata.remove(data);
            Common::Localsocket_CaculatedataLock.unlock();
            M_Socket *tcpsocket=Common::GetTcp_Socket();
            if(tcpsocket==NULL)
            {
                qDebug()<<"当前无法连接负载均衡服务器!";
                return ;
            }
            emit this->t_SocketSendData(this->id,"任务失败",data,tcpsocket->t_socket,One,"");
        }
    }
    if(type!="handle")
        qDebug()<<id<<type<<data<<"local";
}


void Handle::handle_tcpSocket(QString id, QString type, QString data,tcp_socket *t_socket,Handle *handle,emit_type te_ype)
{


    if (te_ype==One&&handle!=this)
    {
        return;
    }

    if(data.size()<100)
    {
        qDebug()<<id<<type<<data;
    }else{
        qDebug()<<id<<type<<"tcp";
    }

    if(type=="传输DLL")
    {
        QStringList  data1=data.split("&&@@");
        if(data1.size()<2)
        {
            qDebug()<<"传输DLL出错!";
            emit this->t_SocketSendData(this->id,"DLL传输出错","存在同名DLL!",t_socket,One,"");
            return;
        }
        QString dll_Name=data1[0];
        QString dll_Data=data1[1];
        QString file_path=QCoreApplication::applicationDirPath()+"\\"+"DLL"+"\\"+dll_Name;
        isDirExist(QCoreApplication::applicationDirPath()+"\\"+"DLL");
        if(isFileExist(file_path))
        {
            qDebug()<<"存在同名DLL!!";
            QString dllmd5=GetMD5(QByteArray::fromBase64(dll_Data.toLatin1()));
            QFile file(file_path);
            if(!file.open(QIODevice::ReadOnly))
            {
                return;
            }
            QByteArray dllData= file.readAll();
            file.close();
            QString thismd5=GetMD5(dllData);
            //当MD5相同则不替换
            if(thismd5==dllmd5)
            {
                emit this->t_SocketSendData(id,type,data,t_socket,All,"计算节点");
            }
            else
            {
                QFile  file(file_path);
                if (file.open(QFile::WriteOnly|QFile::Truncate))
                {
                    QByteArray data1=QByteArray::fromBase64(dll_Data.toLatin1());
                    file.write(data1);
                    file.close();
                }
                else
                {
                    qDebug()<<"写入DLL失败!!";
                    emit this->t_SocketSendData(id,type,"写入Dll失败",t_socket,One,"");
                    return ;
                }
            }
            return ;
        }
        QFile  file(file_path);
        if (file.open(QIODevice::Append))
        {
            QByteArray data1=QByteArray::fromBase64(dll_Data.toLatin1());
            file.write(data1);
            file.close();
        }
        else
        {
            qDebug()<<"写入DLL失败!!";
            emit this->t_SocketSendData(this->id,"DLL传输出错","写入Dll失败",t_socket,One,"");
            return ;
        }
        qDebug()<<"接受DLL成功!DLL名称:"<<dll_Name;

    }
    else if(type=="获取程序类型")
    {
        emit this->t_SocketSendData(this->id,"程序类型","计算节点",t_socket,One,"");
        emit this->t_SocketSendData(this->id,"DLL效验","",t_socket,One,"");
        M_Socket *localsocket=Common::GetLocal_Socket();
        if (localsocket==NULL)
        {
            qDebug()<<"当前没有计算模块连接！";
            return;
        }
        emit this->l_SocketSendData("计算节点","计算模块状态","",localsocket->l_socket,One,"");
    }
    else if(type=="计算任务")
    {
        M_Socket *localsocket=Common::GetLocal_Socket();
        if(localsocket==NULL)
        {
            qDebug()<<"计算模块未连接!";
            LocalSocket_SetUnfinshsenddata("计算节点","handle",data,One,"");
            return;
        }

        QStringList taskdata=data.split("**&&##");
        if(data.size()<3)
        {
            qDebug()<<"任务解析出错!";
            return;
        }
        QString id=taskdata[0];
        LocalSocket_SendData Caclate_Task={id,"handle",data,One,""};
        Common::Localsocket_CaculatedataLock.lockForWrite();
        Common::Localsocket_Caculatedata[id]= Caclate_Task;
        Common::Localsocket_CaculatedataLock.unlock();

        emit this->l_SocketSendData("计算节点","handle",data,localsocket->l_socket,One,"");

    }
    else if(type=="DLL效验")
    {
        QStringList dllinformation=data.split("@@");
        QStringList LackDLLname;
        //如果不存在文件夹则需要服务器传输所有DLL
        if(!isDirExist(QCoreApplication::applicationDirPath()+"\\"+"DLL"))
        {
            for(int a=0;a<dllinformation.size();a++)
            {
                QStringList dlldata=dllinformation[a].split("$$");
                if(dlldata.size()!=2)
                {
                    qDebug()<<"DLL信息损坏!";
                    continue;
                }
                QString dllname=dlldata[0];
                LackDLLname.append(dllname);
            }

        }
        else
        {
            for(int a=0;a<dllinformation.size();a++)
            {
                QStringList dlldata=dllinformation[a].split("$$");
                if(dlldata.size()!=2)
                {
                    qDebug()<<"DLL信息损坏!";
                    continue;
                }
                QString dllname=dlldata[0];
                QString dllmd5=dlldata[1];
                QString file_path=QCoreApplication::applicationDirPath()+"\\"+"DLL"+"\\"+dllname;
                if(!isFileExist(file_path))
                {
                    LackDLLname.append(dllname);
                    continue;
                }
                QFile file(file_path);
                if(!file.open(QIODevice::ReadOnly))
                {
                    qDebug()<<"打开"<<dllname<<"失败!";
                    return;
                }
                QByteArray dllData= file.readAll();
                file.close();
                QString thismd5=GetMD5(dllData);
                if(dllmd5!=thismd5)
                {
                    LackDLLname.append(dllname);
                }
            }
        }
        if(!LackDLLname.isEmpty())
        {
            emit this->t_SocketSendData(this->id,"缺失DLL",LackDLLname.join("@@"),t_socket,One,"");
        }
        else
        {
            emit this->t_SocketSendData(this->id,"DLL完整","",t_socket,One,"");
        }
        // qDebug()<<LackDLLname;
    }



}

bool Handle::isFileExist(QString fullFileName)
{

    QFileInfo fileInfo(fullFileName);

    if(fileInfo.isFile())
    {
        return true;
    }
    return false;
}


bool Handle::isDirExist(QString fullPath)
{
    QDir dir(fullPath);
    if(dir.exists())
    {
        return true;
    }
    else
    {
        bool ok = dir.mkdir(fullPath);//只创建一级子目录，即必须保证上级目录存在
        return false;
    }
}


QStringList Handle::get_computerinfo()                     //获取计算机配置信息
{
    QStringList computer_data;
    SYSTEM_INFO systemInfo;
    GetSystemInfo(&systemInfo);
    computer_data<< QString::number(systemInfo.dwActiveProcessorMask);
    computer_data<< QString::number(systemInfo.dwNumberOfProcessors);
    computer_data<< QString::number(systemInfo.dwPageSize);
    computer_data<< QString::number(systemInfo.dwProcessorType);
    computer_data<< QString::number(systemInfo.wProcessorLevel);
    computer_data<< QString::number(systemInfo.wProcessorRevision);
    MEMORYSTATUSEX statex;
    statex.dwLength = sizeof (statex);
    GlobalMemoryStatusEx (&statex);
    computer_data<< QString::number(statex.dwMemoryLoad);
    computer_data<< QString::number(statex.ullTotalPhys/MB);
    computer_data<< QString::number(statex.ullAvailPhys/MB);



    //    qDebug() << ("处理器掩码:") << systemInfo.dwActiveProcessorMask;

    //    qDebug() << ("处理器个数:") << systemInfo.dwNumberOfProcessors;

    //    qDebug() << ("处理器分页大小:") << systemInfo.dwPageSize;

    //    qDebug() << ("处理器类型:") << systemInfo.dwProcessorType;

    //    qDebug() << ("处理器等级:") << systemInfo.wProcessorLevel;

    //    qDebug() << ("处理器版本:") << systemInfo.wProcessorRevision;

    //    qDebug() << ("物理内存使用率:") << statex.dwMemoryLoad;

    //    qDebug() << ("物理内存总量:") << statex.ullTotalPhys/MB;

    //    qDebug() << ("可用的物理内存:") << statex.ullAvailPhys/MB;
    return computer_data;
}

void Handle::LocalSockt_unfinshsenddata(local_socket *l_socket)
{
    Common::Localsocket_unsenddataLock.lockForWrite();
    for(int a=0;a<Common::Localsocket_unsenddata.size();a++)
    {
        l_socket->send_message(Common::Localsocket_unsenddata[a].id,Common::Localsocket_unsenddata[a].type,Common::Localsocket_unsenddata[a].data);
        if(Common::Localsocket_unsenddata[a].type=="handle")
        {
            QStringList data=Common::Localsocket_unsenddata[a].data.split("**&&##");
            if(data.size()<3)
            {
                qDebug()<<"任务解析出错!";
                continue;
            }
            QString id=data[0];
            Common::Localsocket_CaculatedataLock.lockForWrite();
            Common::Localsocket_Caculatedata[id]=Common::Localsocket_unsenddata[a];
            Common::Localsocket_CaculatedataLock.unlock();
        }
    }
    Common::Localsocket_unsenddata.clear();
    Common::Localsocket_unsenddataLock.unlock();
}

void Handle::LocalSocket_SetUnfinshsenddata(QString id,QString type,QString data,emit_type emittype,QString sockettype)
{
    Common::Localsocket_unsenddataLock.lockForWrite();
    struct LocalSocket_SendData data1={id,type,data,emittype,sockettype};
    Common::Localsocket_unsenddata.append(data1);
    Common::Localsocket_unsenddataLock.unlock();
}


QString Handle::GetMD5(QByteArray data)
{
    QByteArray md5 = QCryptographicHash::hash(data, QCryptographicHash::Md5);
    return   QString(md5.toHex());
}
